source('../settings/settings.R')
source('commonFunctions.R')
persons <- SELECTED_SUBJECTS
drive <- 4

inputFile <- str_interp('../data/processed/distancewise/TT1_Drive_${drive}_${distPrev}m_${distNext}m.csv', list(drive=drive, distPrev=30, distNext=30))
outputFile <- str_interp("../data/processed/analysis/TT1_Drive_${drive}_PP_${distPrev}m_${distNext}m.csv", list(drive=drive, distPrev=30, distNext=30))

all_Drive4 <- read.csv(inputFile)
all_Drive4$Subject <- as.factor(all_Drive4$Subject)
all_Drive4$logPerspiration <- log(all_Drive4$Perspiration)

# starting_points = c( 669 , 668 , 676 , 687 , 680 ,  676 ,  678 ,
#                      693 , 722 , 723 , 677 , 679 ,  711 ,  707 ,  
#                      699 , 679 , 684 , 688 , 686 ,  696 ,  702 )
# 
# ending_points   = c( 741 , 786 , 749 , 782 , 736 ,  756 ,  768 ,  
#                      812 , 853 , 792 , 783 , 772 ,  799 ,  781 ,  
#                      777 , 763 , 795 , 791 , 832 ,  755 ,  758 )

peak_points     = c( 67 ,  86 ,  73 ,  73 ,  73 ,  64 ,  73 ,  
                     79 ,  69 ,  64 ,  68 ,  67 ,  77 ,  68 ,  
                     82 ,  67 ,  72 ,  72 ,  71 ,  68 ,  64 )

# Driving time
driving_times = vector(mode="list", length = length(persons))
names(driving_times) <- persons

activity_names = vector(mode="list", length = length(persons))
names(activity_names) <- persons

acc_start_times = vector(mode="list", length = length(persons))
names(acc_start_times) <- persons
acc_end_times = vector(mode="list", length = length(persons))
names(acc_end_times) <- persons

stressor_start_times = vector(mode="list", length = length(persons))
names(stressor_start_times) <- persons
stressor_end_times = vector(mode="list", length = length(persons))
names(stressor_end_times) <- persons

complete_times = vector(mode="list", length = length(persons))
names(complete_times) <- persons

data_baseline = vector(mode="list", length=length(persons))
pp_baseline = vector(mode="list", length=length(persons))

names(data_baseline) <- persons
names(pp_baseline) <- persons

# Number of peaks

PREV_DISTANCE = 300
TRACKING_DISTANCE = 60
DRIVE_MODE = 4
getActivityName <- function(x, fullname=F) {
  if(x == 1) return(ifelse(fullname, "Normal", "NO"))
  if(x == 2) return(ifelse(fullname, "Cognitive", "C"))
  if(x == 3) return(ifelse(fullname, "Motoric", "M"))
}

for (p in persons) {
  pData <- all_Drive4[all_Drive4$Subject==as.integer(p) | all_Drive4$Subject==p,]
  pAcc <- pData[pData$Failure>0.5,] # Failure = 1
  acc_start_times[[p]] <- min(pAcc$Distance)
  acc_end_times[[p]] <- max(pAcc$Distance)
  
  activity_names[[p]] <- getActivityName(pData[pData$Time==60,]$Activity, fullname = T)
  
  pStressor = pData[pData$Activity>1.5,] # Stressor = 2, 3
  if (nrow(pStressor) > 0) {
    stressor_start_times[[p]] <- min(pStressor$Distance)
    stressor_end_times[[p]] <- max(pStressor$Distance)
  } else {
    stressor_start_times[[p]] <- NULL
    stressor_end_times[[p]] <- NULL
  }
}
DELAY_DISTANCE <- 10

idx <- 1
plt_AllAcc <- vector(mode="list", length=length(persons)) 
names(plt_AllAcc) <- persons

COLOR_ACC = "#02A3C8"
COLOR_PP = "#F28E8E"
COLOR_BRAKE = "#888888"

y1 <- list(
  tickfont = list(color = COLOR_ACC),
  title="Degree",
  range=c(0, 100)
)
y2 <- list(
  tickfont = list(color = COLOR_PP),
  overlaying = "y",
  side = "right",
  title = "Log Perspiration",
  showgrid = FALSE,
  range=c(min(all_Drive4$ppLogNormalized), max(all_Drive4$ppLogNormalized))
)
  
for (p in persons) {
  pData <- all_Drive4[all_Drive4$Subject==as.integer(p) | all_Drive4$Subject==p,]
  
  # Baseline
  data_baseline[[p]] <- read.csv(str_interp("../data/processed/drives/T0${person}/T0${person}_Drive_1.csv", list(person=p)))
  # Compute the mean
  p_pp_nr <- data_baseline[[p]]$Perspiration
  p_pp_nr <- p_pp_nr[!is.na(p_pp_nr)]
  pp_baseline[[p]] <- log(mean(p_pp_nr))
  
  # Incident
  driving_times[[p]] <- max(pData$Distance)
  
  incident_starting_time <- acc_start_times[[p]] # starting_points[idx]
  incident_ending_time <- acc_end_times[[p]]
  complete_times[[p]] <- ifelse(incident_starting_time + TRACKING_DISTANCE > driving_times[[p]], driving_times[[p]], incident_starting_time + TRACKING_DISTANCE)
  
  from_time <- ifelse(incident_starting_time - PREV_DISTANCE >= 0, incident_starting_time - PREV_DISTANCE, 0)
  to_time <- complete_times[[p]]
  
  # print(paste("From", from_time))
  # print(paste("Incident", incident_starting_time))
  # print(paste("To", to_time))
  
    
  pDataBefore <- pData[pData$Distance < incident_starting_time & pData$Distance >= from_time,]
  pDataAfter <- pData[pData$Distance >= incident_starting_time + DELAY_DISTANCE & pData$Distance <= to_time,]
  
  # print(nrow(pDataBefore))
  # print(nrow(pDataAfter))
  
  ppMeanBefore <- mean(pDataBefore$ppLogNormalized)
  ppMeanAfter <- mean(pDataAfter$ppLogNormalized)
  
  dir.create(file.path('../figures/drive/', paste0('Drive_', DRIVE_MODE)), showWarnings = FALSE)
  fname <- str_interp('../figures/drive/Drive_${drive}/P${person}.svg', list(drive=DRIVE_MODE, person=p)) 
  
  pData <- pData[pData$Distance >= from_time,]
  plot_Acc <- plot_ly(pData, x = ~Distance, height=400, width=900) %>%
              add_trace(name="Acceleration", y = ~Acceleration, type = 'scatter', mode = 'lines', line=list(width=1.5, color=COLOR_ACC)) %>% 
              add_trace(name="Brake", y = ~Braking, type = 'scatter', mode = 'lines', line=list(width=1.5, color=COLOR_BRAKE)) %>%
              add_trace(name="PP", y = ~ppLogNormalized, type = 'scatter', mode = 'lines', line=list(width=1.5, color=COLOR_PP), yaxis = "y2") %>% 
              add_segments(x = min(pData$Distance), xend = max(pData$Distance), y = ppMeanBefore, yend = ppMeanBefore, 
                           yaxis = "y2", name="Mean PP (Before Incident)",
                           line=list(color=COLOR_PP, dash = 'dot')) %>%
              add_segments(x = min(pData$Distance), xend = max(pData$Distance), y = ppMeanAfter, yend = ppMeanAfter, 
                           yaxis = "y2", name="Mean PP (After Incident)",
                           line=list(color="darkred", dash = 'dot')) %>%
              # add_segments(x = min(pData$Distance) - 0.1, xend = max(pData$Distance), y = pp_baseline[[p]], yend = pp_baseline[[p]], 
              #              yaxis = "y2", name="Baseline PP (from Drive 1)",
              #              line=list(color="blue", dash = 'dot')) %>%
    
              layout(
                title=paste0("Subject #", p, " (Stressor=", activity_names[[p]], ")"), 
                xaxis=list(title="Distance [m]", range=c(0)), 
                yaxis=y1, 
                yaxis2=y2, 
                margin = list(l = 50, r = 50, b = 50, t = 50, pad = 4),
                shapes = list(
                  # Holistic period
                  list(type = "rect", fillcolor = "red", 
                       line = list(color = "red"), opacity = 0.3,
                      x0 = incident_starting_time, x1 = incident_ending_time, xref = "x",
                      y0 = 0, y1 = 100, yref = "y"),
                  # Stressor period
                  list(type = "rect", fillcolor = "yellow", 
                       line = list(color = "yellow"), opacity = 0.1,
                      x0 = stressor_start_times[[p]], x1 = incident_starting_time, xref = "x",
                      y0 = 0, y1 = 100, yref = "y"),
                  list(type = "rect", fillcolor = "yellow", 
                       line = list(color = "yellow"), opacity = 0.1,
                      x0 = incident_ending_time, x1 = stressor_end_times[[p]], xref = "x",
                      y0 = 0, y1 = 100, yref = "y")
                ),
                legend = list(x = 0.1, y = 1, bgcolor = "rgba(0,0,0,0)", title="Metric"),
                autosize = F
              )
  
  # orca(plot_PP, fname)
  idx <- idx + 1
  plt_AllAcc[[p]] <- plot_Acc
}

htmltools::tagList(plt_AllAcc)
# for (p in persons) {
#   # Save image
#   orca(plt_AllAcc[[p]], file = paste0("../plots/drive/Drive_4/T0", p, ".png"), scale = 2)
# }
idx <- 1
behavioralColumns <- c("Subject", 
                       "Brake_u", 
                       "Brake_std", 
                       "PP_before",
                       "PP_u",  
                       "PP_std",
                       "PP_dev")
behavioralMatrix <- matrix(nrow=length(persons), ncol = length(behavioralColumns))

# Careful about Subject 09
# selected_persons <- persons[persons != "09"]

for (p in persons) {
  pData <- all_Drive4[all_Drive4$Subject==as.integer(p) | all_Drive4$Subject==p,]
  
  incident_starting_time <- acc_start_times[[p]] # starting_points[idx]
  incident_ending_time <- acc_end_times[[p]]
  
  from_time <- ifelse(incident_starting_time - PREV_DISTANCE >= 0, incident_starting_time - PREV_DISTANCE, 0)
  to_time <- complete_times[[p]]
    
  dfBefore <- pData[pData$Distance < incident_starting_time & pData$Distance >= from_time,]
  dfAfter <- pData[pData$Distance >= incident_starting_time + DELAY_DISTANCE  & pData$Distance <= to_time,]
  
  # diffSpeed <- mean(dfAfter$Speed) - mean(dfBefore$Speed)
  brakeMean <- mean(dfAfter$Braking)
  brakeStd <- mean(dfAfter$Braking)
  
  ppMean <- mean(dfAfter$ppLogNormalized)
  ppBefore <- mean(dfBefore$ppLogNormalized)
  ppStd <- sd(dfAfter$ppLogNormalized)
  
  mid_avg <- (pp_baseline[[p]] + mean(dfBefore$ppLogNormalized)) / 2
    
  diffPP <- mean(dfAfter$ppLogNormalized) - mean(dfBefore$ppLogNormalized)
  
  behavioralMatrix[idx, ] <- c(p, 
                               round(brakeMean, digits=5), 
                               round(brakeStd, digits=5),
                               round(ppBefore, digits=5),
                               round(ppMean, digits = 5),
                               round(ppStd, digits=5),
                               round(diffPP, digits=5))
  idx <- idx + 1
}

# behavioralMatrix

behavioralDf <- as.data.frame(behavioralMatrix, stringsAsFactors=FALSE)
names(behavioralDf) <- behavioralColumns

behavioralDf
NA
clusteringDf <- behavioralDf
clusteringDf$Subject <- NULL
# clusteringDf$PP_dev_norm <- as.numeric(clusteringDf$PP_dev) / as.numeric(clusteringDf$PP_u)
# clusteringDf$PP_std_norm <- as.numeric(clusteringDf$PP_std) / as.numeric(clusteringDf$PP_u)
clusteringDf$Brake_u <- NULL
clusteringDf$Brake_std <- NULL
clusteringDf$PP_before <- NULL
clusteringDf$PP_u <- NULL
clusteringDf$PP_std <- NULL
# clusteringDf$PP_dev <- NULL

rownames(clusteringDf) <- paste0("#", persons)

for (col in names(clusteringDf)) {
  clusteringDf[,col] <- as.numeric(as.character(clusteringDf[, col]))
  # clusteringDf[,col] <- scale(clusteringDf[,col])
}
clusteringDf
dfActivity <- all_Drive4[all_Drive4$Time==60,] %>% select(c("Subject", "Activity"))
dfActivity$ActivityName <- sapply(dfActivity$Activity, getActivityName)
dfActivity$Subject <- as.factor(dfActivity$Subject)
rownames(dfActivity) <- NULL
dfActivity %>% select(c("Subject", "ActivityName"))
library(dendextend)

NUMBER_OF_CLUSTERS = 3

color_darkpink = "#e75480"
CLUSTER_BRANCH_COLORS <- c("blue", "red", color_darkpink)[1:NUMBER_OF_CLUSTERS]
CLUSTER_LABEL_COLORS <- c("blue", "red", color_darkpink)[1:NUMBER_OF_CLUSTERS]

behavioralMatrixClustering <- as.matrix(clusteringDf)
rownames(behavioralMatrixClustering) <- paste0(dfActivity$ActivityName, " - #", persons)
distMatrix <- dist(behavioralMatrixClustering, method="manhattan")
hresults <- distMatrix %>% hclust

hc <- hresults %>% 
      as.dendrogram %>%
      set("nodes_cex", NUMBER_OF_CLUSTERS) %>%
      set("labels_col", value = CLUSTER_LABEL_COLORS, k=NUMBER_OF_CLUSTERS) %>%
      # set("leaves_pch", 19) %>%
      # set("leaves_col", value = c("gray"), k=NUMBER_OF_CLUSTERS) %>%    
      set("branches_k_color", value=CLUSTER_BRANCH_COLORS, k=NUMBER_OF_CLUSTERS)

plot(hc)
legend("topright", 
     title="Drive=Failure \nChange of Arousal",
     legend = c("Exceptional Increase" , "Noticable Increase" , "No-change or Decrease"), 
     col = c("red", "pink" , "blue"),
     pch = c(20,20,20), bty = "n",  pt.cex = 1.5, cex = 0.8 , 
     text.col = "black", horiz = FALSE, inset = c(0.0, 0.1))

NUMBER_OF_CLUSTERS = 2

color_darkpink = "#e75480"
CLUSTER_BRANCH_COLORS <- c("blue", "red", color_darkpink)[1:NUMBER_OF_CLUSTERS]
CLUSTER_LABEL_COLORS <- c("blue", "red", color_darkpink)[1:NUMBER_OF_CLUSTERS]

behavioralMatrixClustering <- as.matrix(clusteringDf)
rownames(behavioralMatrixClustering) <- paste0(dfActivity$ActivityName, " - #", persons)
distMatrix <- dist(behavioralMatrixClustering, method="manhattan", diag = T)
hresults <- distMatrix %>% hclust(method="average")

hc <- hresults %>% 
      as.dendrogram %>%
      set("nodes_cex", NUMBER_OF_CLUSTERS) %>%
      set("labels_col", value = CLUSTER_LABEL_COLORS, k=NUMBER_OF_CLUSTERS) %>%
      # set("leaves_pch", 19) %>%
      # set("leaves_col", value = c("gray"), k=NUMBER_OF_CLUSTERS) %>%    
      set("branches_k_color", value=CLUSTER_BRANCH_COLORS, k=NUMBER_OF_CLUSTERS)

plot(hc)
legend("topright", 
     title="Drive=Failure \nChange of Arousal",
     legend = c("Accelerophobia" , "Normal"), 
     col = c("red", "blue"),
     pch = c(20,20,20), bty = "n",  pt.cex = 1.5, cex = 0.8 , 
     text.col = "black", horiz = FALSE, inset = c(0.0, 0.1))

# Store clustering data
dfx <- clusteringDf
dfx <- cbind(persons, as.numeric(behavioralDf$PP_before), as.numeric(behavioralDf$PP_u), dfx, dfActivity$ActivityName)
names(dfx) <- c("Subject", "PP_Prior", "PP_After", "PP_Dev", "Activity")

# Normalize
dfx <- dfx %>% mutate(PP_Dev_Normalized = ifelse(PP_Prior > 0, PP_After, PP_After - PP_Prior))
write.csv(dfx, outputFile, row.names = F)
library(cluster)
fit <- kmeans(clusteringDf, 2)
clusplot(clusteringDf, fit$cluster, color=TRUE, shade=TRUE,
   labels=2, lines=0)

silhouette_score <- function(k){
  km <- kmeans(clusteringDf, centers = k, nstart=25)
  ss <- silhouette(km$cluster, dist(clusteringDf))
  mean(ss[, 3])
}
k <- 2:10
avg_sil <- sapply(k, silhouette_score)
plot(k, type='b', avg_sil, xlab='Number of clusters', ylab='Average Silhouette Scores', frame=FALSE)

Linear Model

sampledData <- getSampleSegmentedData(NA, all_Drive4, window=2)
linearModelOnline <- lmer(ppNext ~ 
              (1 | Subject)
              + Speed_u
              + Speed_std
              + Acc_u
              + Acc_std
              + Brake_u
              + Brake_std
              + Steering_u
              + Steering_std, 
            data=sampledData, REML = T)

# lmer(ppLogNormalized ~ (1 | Subject) + Speed_u + Speed_std + Acc_u + Acc_std + Brake_u + Brake_std + Steering_u + Steering_std + HR + BR, data = pData, REML = T)

# anova(model)
summary(linearModelOnline)
Linear mixed model fit by REML. t-tests use Satterthwaite's method ['lmerModLmerTest']
Formula: ppNext ~ (1 | Subject) + Speed_u + Speed_std + Acc_u + Acc_std +      Brake_u + Brake_std + Steering_u + Steering_std
   Data: sampledData

REML criterion at convergence: -1352.9

Scaled residuals: 
    Min      1Q  Median      3Q     Max 
-2.4668 -0.6034 -0.0884  0.5493  5.5490 

Random effects:
 Groups   Name        Variance Std.Dev.
 Subject  (Intercept) 0.015927 0.12620 
 Residual             0.007908 0.08893 
Number of obs: 775, groups:  Subject, 21

Fixed effects:
               Estimate Std. Error         df t value Pr(>|t|)    
(Intercept)   3.994e-02  3.124e-02  3.184e+01   1.278   0.2103    
Speed_u      -5.214e-04  5.083e-04  7.471e+02  -1.026   0.3053    
Speed_std     5.737e-03  2.795e-03  7.467e+02   2.053   0.0405 *  
Acc_u        -1.140e-04  4.334e-04  7.472e+02  -0.263   0.7925    
Acc_std       1.666e-03  8.636e-04  7.463e+02   1.929   0.0541 .  
Brake_u       3.263e-03  4.323e-04  7.469e+02   7.548 1.29e-13 ***
Brake_std     3.042e-04  7.076e-04  7.482e+02   0.430   0.6673    
Steering_u   -2.200e-04  5.226e-05  7.506e+02  -4.211 2.85e-05 ***
Steering_std -9.907e-05  1.384e-04  7.472e+02  -0.716   0.4744    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Correlation of Fixed Effects:
            (Intr) Speed_ Spd_st Acc_u  Acc_st Brake_ Brk_st Sterng_
Speed_u     -0.409                                                  
Speed_std   -0.027  0.054                                           
Acc_u       -0.129 -0.155 -0.147                                    
Acc_std      0.081 -0.043 -0.052 -0.494                             
Brake_u     -0.131  0.145 -0.657  0.316 -0.077                      
Brake_std   -0.275  0.563  0.328  0.032 -0.149 -0.312               
Steering_u  -0.008  0.009  0.095 -0.013  0.019 -0.079 -0.036        
Steerng_std -0.100  0.206 -0.398  0.110 -0.204  0.385 -0.349 -0.058 
plot(linearModelOnline)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnNvdXJjZSgnLi4vc2V0dGluZ3Mvc2V0dGluZ3MuUicpCnNvdXJjZSgnY29tbW9uRnVuY3Rpb25zLlInKQpgYGAKCmBgYHtyfQpwZXJzb25zIDwtIFNFTEVDVEVEX1NVQkpFQ1RTCmRyaXZlIDwtIDQKCmlucHV0RmlsZSA8LSBzdHJfaW50ZXJwKCcuLi9kYXRhL3Byb2Nlc3NlZC9kaXN0YW5jZXdpc2UvVFQxX0RyaXZlXyR7ZHJpdmV9XyR7ZGlzdFByZXZ9bV8ke2Rpc3ROZXh0fW0uY3N2JywgbGlzdChkcml2ZT1kcml2ZSwgZGlzdFByZXY9MzAsIGRpc3ROZXh0PTMwKSkKb3V0cHV0RmlsZSA8LSBzdHJfaW50ZXJwKCIuLi9kYXRhL3Byb2Nlc3NlZC9hbmFseXNpcy9UVDFfRHJpdmVfJHtkcml2ZX1fUFBfJHtkaXN0UHJldn1tXyR7ZGlzdE5leHR9bS5jc3YiLCBsaXN0KGRyaXZlPWRyaXZlLCBkaXN0UHJldj0zMCwgZGlzdE5leHQ9MzApKQoKYWxsX0RyaXZlNCA8LSByZWFkLmNzdihpbnB1dEZpbGUpCmFsbF9Ecml2ZTQkU3ViamVjdCA8LSBhcy5mYWN0b3IoYWxsX0RyaXZlNCRTdWJqZWN0KQphbGxfRHJpdmU0JGxvZ1BlcnNwaXJhdGlvbiA8LSBsb2coYWxsX0RyaXZlNCRQZXJzcGlyYXRpb24pCgojIHN0YXJ0aW5nX3BvaW50cyA9IGMoIDY2OSAsIDY2OCAsIDY3NiAsIDY4NyAsIDY4MCAsICA2NzYgLCAgNjc4ICwKIyAgICAgICAgICAgICAgICAgICAgICA2OTMgLCA3MjIgLCA3MjMgLCA2NzcgLCA2NzkgLCAgNzExICwgIDcwNyAsICAKIyAgICAgICAgICAgICAgICAgICAgICA2OTkgLCA2NzkgLCA2ODQgLCA2ODggLCA2ODYgLCAgNjk2ICwgIDcwMiApCiMgCiMgZW5kaW5nX3BvaW50cyAgID0gYyggNzQxICwgNzg2ICwgNzQ5ICwgNzgyICwgNzM2ICwgIDc1NiAsICA3NjggLCAgCiMgICAgICAgICAgICAgICAgICAgICAgODEyICwgODUzICwgNzkyICwgNzgzICwgNzcyICwgIDc5OSAsICA3ODEgLCAgCiMgICAgICAgICAgICAgICAgICAgICAgNzc3ICwgNzYzICwgNzk1ICwgNzkxICwgODMyICwgIDc1NSAsICA3NTggKQoKcGVha19wb2ludHMgICAgID0gYyggNjcgLCAgODYgLCAgNzMgLCAgNzMgLCAgNzMgLCAgNjQgLCAgNzMgLCAgCiAgICAgICAgICAgICAgICAgICAgIDc5ICwgIDY5ICwgIDY0ICwgIDY4ICwgIDY3ICwgIDc3ICwgIDY4ICwgIAogICAgICAgICAgICAgICAgICAgICA4MiAsICA2NyAsICA3MiAsICA3MiAsICA3MSAsICA2OCAsICA2NCApCgojIERyaXZpbmcgdGltZQpkcml2aW5nX3RpbWVzID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGggPSBsZW5ndGgocGVyc29ucykpCm5hbWVzKGRyaXZpbmdfdGltZXMpIDwtIHBlcnNvbnMKCmFjdGl2aXR5X25hbWVzID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGggPSBsZW5ndGgocGVyc29ucykpCm5hbWVzKGFjdGl2aXR5X25hbWVzKSA8LSBwZXJzb25zCgphY2Nfc3RhcnRfdGltZXMgPSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aCA9IGxlbmd0aChwZXJzb25zKSkKbmFtZXMoYWNjX3N0YXJ0X3RpbWVzKSA8LSBwZXJzb25zCmFjY19lbmRfdGltZXMgPSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aCA9IGxlbmd0aChwZXJzb25zKSkKbmFtZXMoYWNjX2VuZF90aW1lcykgPC0gcGVyc29ucwoKc3RyZXNzb3Jfc3RhcnRfdGltZXMgPSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aCA9IGxlbmd0aChwZXJzb25zKSkKbmFtZXMoc3RyZXNzb3Jfc3RhcnRfdGltZXMpIDwtIHBlcnNvbnMKc3RyZXNzb3JfZW5kX3RpbWVzID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGggPSBsZW5ndGgocGVyc29ucykpCm5hbWVzKHN0cmVzc29yX2VuZF90aW1lcykgPC0gcGVyc29ucwoKY29tcGxldGVfdGltZXMgPSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aCA9IGxlbmd0aChwZXJzb25zKSkKbmFtZXMoY29tcGxldGVfdGltZXMpIDwtIHBlcnNvbnMKCmRhdGFfYmFzZWxpbmUgPSB2ZWN0b3IobW9kZT0ibGlzdCIsIGxlbmd0aD1sZW5ndGgocGVyc29ucykpCnBwX2Jhc2VsaW5lID0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9bGVuZ3RoKHBlcnNvbnMpKQoKbmFtZXMoZGF0YV9iYXNlbGluZSkgPC0gcGVyc29ucwpuYW1lcyhwcF9iYXNlbGluZSkgPC0gcGVyc29ucwoKIyBOdW1iZXIgb2YgcGVha3MKClBSRVZfRElTVEFOQ0UgPSAzMDAKVFJBQ0tJTkdfRElTVEFOQ0UgPSA2MApEUklWRV9NT0RFID0gNApgYGAKCmBgYHtyfQpnZXRBY3Rpdml0eU5hbWUgPC0gZnVuY3Rpb24oeCwgZnVsbG5hbWU9RikgewogIGlmKHggPT0gMSkgcmV0dXJuKGlmZWxzZShmdWxsbmFtZSwgIk5vcm1hbCIsICJOTyIpKQogIGlmKHggPT0gMikgcmV0dXJuKGlmZWxzZShmdWxsbmFtZSwgIkNvZ25pdGl2ZSIsICJDIikpCiAgaWYoeCA9PSAzKSByZXR1cm4oaWZlbHNlKGZ1bGxuYW1lLCAiTW90b3JpYyIsICJNIikpCn0KCmZvciAocCBpbiBwZXJzb25zKSB7CiAgcERhdGEgPC0gYWxsX0RyaXZlNFthbGxfRHJpdmU0JFN1YmplY3Q9PWFzLmludGVnZXIocCkgfCBhbGxfRHJpdmU0JFN1YmplY3Q9PXAsXQogIHBBY2MgPC0gcERhdGFbcERhdGEkRmFpbHVyZT4wLjUsXSAjIEZhaWx1cmUgPSAxCiAgYWNjX3N0YXJ0X3RpbWVzW1twXV0gPC0gbWluKHBBY2MkRGlzdGFuY2UpCiAgYWNjX2VuZF90aW1lc1tbcF1dIDwtIG1heChwQWNjJERpc3RhbmNlKQogIAogIGFjdGl2aXR5X25hbWVzW1twXV0gPC0gZ2V0QWN0aXZpdHlOYW1lKHBEYXRhW3BEYXRhJFRpbWU9PTYwLF0kQWN0aXZpdHksIGZ1bGxuYW1lID0gVCkKICAKICBwU3RyZXNzb3IgPSBwRGF0YVtwRGF0YSRBY3Rpdml0eT4xLjUsXSAjIFN0cmVzc29yID0gMiwgMwogIGlmIChucm93KHBTdHJlc3NvcikgPiAwKSB7CiAgICBzdHJlc3Nvcl9zdGFydF90aW1lc1tbcF1dIDwtIG1pbihwU3RyZXNzb3IkRGlzdGFuY2UpCiAgICBzdHJlc3Nvcl9lbmRfdGltZXNbW3BdXSA8LSBtYXgocFN0cmVzc29yJERpc3RhbmNlKQogIH0gZWxzZSB7CiAgICBzdHJlc3Nvcl9zdGFydF90aW1lc1tbcF1dIDwtIE5VTEwKICAgIHN0cmVzc29yX2VuZF90aW1lc1tbcF1dIDwtIE5VTEwKICB9Cn0KYGBgCgpgYGB7cn0KREVMQVlfRElTVEFOQ0UgPC0gMTAKCmlkeCA8LSAxCnBsdF9BbGxBY2MgPC0gdmVjdG9yKG1vZGU9Imxpc3QiLCBsZW5ndGg9bGVuZ3RoKHBlcnNvbnMpKSAKbmFtZXMocGx0X0FsbEFjYykgPC0gcGVyc29ucwoKQ09MT1JfQUNDID0gIiMwMkEzQzgiCkNPTE9SX1BQID0gIiNGMjhFOEUiCkNPTE9SX0JSQUtFID0gIiM4ODg4ODgiCgp5MSA8LSBsaXN0KAogIHRpY2tmb250ID0gbGlzdChjb2xvciA9IENPTE9SX0FDQyksCiAgdGl0bGU9IkRlZ3JlZSIsCiAgcmFuZ2U9YygwLCAxMDApCikKeTIgPC0gbGlzdCgKICB0aWNrZm9udCA9IGxpc3QoY29sb3IgPSBDT0xPUl9QUCksCiAgb3ZlcmxheWluZyA9ICJ5IiwKICBzaWRlID0gInJpZ2h0IiwKICB0aXRsZSA9ICJMb2cgUGVyc3BpcmF0aW9uIiwKICBzaG93Z3JpZCA9IEZBTFNFLAogIHJhbmdlPWMobWluKGFsbF9Ecml2ZTQkcHBMb2dOb3JtYWxpemVkKSwgbWF4KGFsbF9Ecml2ZTQkcHBMb2dOb3JtYWxpemVkKSkKKQogIApmb3IgKHAgaW4gcGVyc29ucykgewogIHBEYXRhIDwtIGFsbF9Ecml2ZTRbYWxsX0RyaXZlNCRTdWJqZWN0PT1hcy5pbnRlZ2VyKHApIHwgYWxsX0RyaXZlNCRTdWJqZWN0PT1wLF0KICAKICAjIEJhc2VsaW5lCiAgZGF0YV9iYXNlbGluZVtbcF1dIDwtIHJlYWQuY3N2KHN0cl9pbnRlcnAoIi4uL2RhdGEvcHJvY2Vzc2VkL2RyaXZlcy9UMCR7cGVyc29ufS9UMCR7cGVyc29ufV9Ecml2ZV8xLmNzdiIsIGxpc3QocGVyc29uPXApKSkKICAjIENvbXB1dGUgdGhlIG1lYW4KICBwX3BwX25yIDwtIGRhdGFfYmFzZWxpbmVbW3BdXSRQZXJzcGlyYXRpb24KICBwX3BwX25yIDwtIHBfcHBfbnJbIWlzLm5hKHBfcHBfbnIpXQogIHBwX2Jhc2VsaW5lW1twXV0gPC0gbG9nKG1lYW4ocF9wcF9ucikpCiAgCiAgIyBJbmNpZGVudAogIGRyaXZpbmdfdGltZXNbW3BdXSA8LSBtYXgocERhdGEkRGlzdGFuY2UpCiAgCiAgaW5jaWRlbnRfc3RhcnRpbmdfdGltZSA8LSBhY2Nfc3RhcnRfdGltZXNbW3BdXSAjIHN0YXJ0aW5nX3BvaW50c1tpZHhdCiAgaW5jaWRlbnRfZW5kaW5nX3RpbWUgPC0gYWNjX2VuZF90aW1lc1tbcF1dCiAgY29tcGxldGVfdGltZXNbW3BdXSA8LSBpZmVsc2UoaW5jaWRlbnRfc3RhcnRpbmdfdGltZSArIFRSQUNLSU5HX0RJU1RBTkNFID4gZHJpdmluZ190aW1lc1tbcF1dLCBkcml2aW5nX3RpbWVzW1twXV0sIGluY2lkZW50X3N0YXJ0aW5nX3RpbWUgKyBUUkFDS0lOR19ESVNUQU5DRSkKICAKICBmcm9tX3RpbWUgPC0gaWZlbHNlKGluY2lkZW50X3N0YXJ0aW5nX3RpbWUgLSBQUkVWX0RJU1RBTkNFID49IDAsIGluY2lkZW50X3N0YXJ0aW5nX3RpbWUgLSBQUkVWX0RJU1RBTkNFLCAwKQogIHRvX3RpbWUgPC0gY29tcGxldGVfdGltZXNbW3BdXQogIAogICMgcHJpbnQocGFzdGUoIkZyb20iLCBmcm9tX3RpbWUpKQogICMgcHJpbnQocGFzdGUoIkluY2lkZW50IiwgaW5jaWRlbnRfc3RhcnRpbmdfdGltZSkpCiAgIyBwcmludChwYXN0ZSgiVG8iLCB0b190aW1lKSkKICAKICAgIAogIHBEYXRhQmVmb3JlIDwtIHBEYXRhW3BEYXRhJERpc3RhbmNlIDwgaW5jaWRlbnRfc3RhcnRpbmdfdGltZSAmIHBEYXRhJERpc3RhbmNlID49IGZyb21fdGltZSxdCiAgcERhdGFBZnRlciA8LSBwRGF0YVtwRGF0YSREaXN0YW5jZSA+PSBpbmNpZGVudF9zdGFydGluZ190aW1lICsgREVMQVlfRElTVEFOQ0UgJiBwRGF0YSREaXN0YW5jZSA8PSB0b190aW1lLF0KICAKICAjIHByaW50KG5yb3cocERhdGFCZWZvcmUpKQogICMgcHJpbnQobnJvdyhwRGF0YUFmdGVyKSkKICAKICBwcE1lYW5CZWZvcmUgPC0gbWVhbihwRGF0YUJlZm9yZSRwcExvZ05vcm1hbGl6ZWQpCiAgcHBNZWFuQWZ0ZXIgPC0gbWVhbihwRGF0YUFmdGVyJHBwTG9nTm9ybWFsaXplZCkKICAKICBkaXIuY3JlYXRlKGZpbGUucGF0aCgnLi4vZmlndXJlcy9kcml2ZS8nLCBwYXN0ZTAoJ0RyaXZlXycsIERSSVZFX01PREUpKSwgc2hvd1dhcm5pbmdzID0gRkFMU0UpCiAgZm5hbWUgPC0gc3RyX2ludGVycCgnLi4vZmlndXJlcy9kcml2ZS9Ecml2ZV8ke2RyaXZlfS9QJHtwZXJzb259LnN2ZycsIGxpc3QoZHJpdmU9RFJJVkVfTU9ERSwgcGVyc29uPXApKSAKICAKICBwRGF0YSA8LSBwRGF0YVtwRGF0YSREaXN0YW5jZSA+PSBmcm9tX3RpbWUsXQogIHBsb3RfQWNjIDwtIHBsb3RfbHkocERhdGEsIHggPSB+RGlzdGFuY2UsIGhlaWdodD00MDAsIHdpZHRoPTkwMCkgJT4lCiAgICAgICAgICAgICAgYWRkX3RyYWNlKG5hbWU9IkFjY2VsZXJhdGlvbiIsIHkgPSB+QWNjZWxlcmF0aW9uLCB0eXBlID0gJ3NjYXR0ZXInLCBtb2RlID0gJ2xpbmVzJywgbGluZT1saXN0KHdpZHRoPTEuNSwgY29sb3I9Q09MT1JfQUNDKSkgJT4lIAogICAgICAgICAgICAgIGFkZF90cmFjZShuYW1lPSJCcmFrZSIsIHkgPSB+QnJha2luZywgdHlwZSA9ICdzY2F0dGVyJywgbW9kZSA9ICdsaW5lcycsIGxpbmU9bGlzdCh3aWR0aD0xLjUsIGNvbG9yPUNPTE9SX0JSQUtFKSkgJT4lCiAgICAgICAgICAgICAgYWRkX3RyYWNlKG5hbWU9IlBQIiwgeSA9IH5wcExvZ05vcm1hbGl6ZWQsIHR5cGUgPSAnc2NhdHRlcicsIG1vZGUgPSAnbGluZXMnLCBsaW5lPWxpc3Qod2lkdGg9MS41LCBjb2xvcj1DT0xPUl9QUCksIHlheGlzID0gInkyIikgJT4lIAogICAgICAgICAgICAgIGFkZF9zZWdtZW50cyh4ID0gbWluKHBEYXRhJERpc3RhbmNlKSwgeGVuZCA9IG1heChwRGF0YSREaXN0YW5jZSksIHkgPSBwcE1lYW5CZWZvcmUsIHllbmQgPSBwcE1lYW5CZWZvcmUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9ICJ5MiIsIG5hbWU9Ik1lYW4gUFAgKEJlZm9yZSBJbmNpZGVudCkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9Q09MT1JfUFAsIGRhc2ggPSAnZG90JykpICU+JQogICAgICAgICAgICAgIGFkZF9zZWdtZW50cyh4ID0gbWluKHBEYXRhJERpc3RhbmNlKSwgeGVuZCA9IG1heChwRGF0YSREaXN0YW5jZSksIHkgPSBwcE1lYW5BZnRlciwgeWVuZCA9IHBwTWVhbkFmdGVyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgeWF4aXMgPSAieTIiLCBuYW1lPSJNZWFuIFBQIChBZnRlciBJbmNpZGVudCkiLAogICAgICAgICAgICAgICAgICAgICAgICAgICBsaW5lPWxpc3QoY29sb3I9ImRhcmtyZWQiLCBkYXNoID0gJ2RvdCcpKSAlPiUKICAgICAgICAgICAgICAjIGFkZF9zZWdtZW50cyh4ID0gbWluKHBEYXRhJERpc3RhbmNlKSAtIDAuMSwgeGVuZCA9IG1heChwRGF0YSREaXN0YW5jZSksIHkgPSBwcF9iYXNlbGluZVtbcF1dLCB5ZW5kID0gcHBfYmFzZWxpbmVbW3BdXSwgCiAgICAgICAgICAgICAgIyAgICAgICAgICAgICAgeWF4aXMgPSAieTIiLCBuYW1lPSJCYXNlbGluZSBQUCAoZnJvbSBEcml2ZSAxKSIsCiAgICAgICAgICAgICAgIyAgICAgICAgICAgICAgbGluZT1saXN0KGNvbG9yPSJibHVlIiwgZGFzaCA9ICdkb3QnKSkgJT4lCiAgICAKICAgICAgICAgICAgICBsYXlvdXQoCiAgICAgICAgICAgICAgICB0aXRsZT1wYXN0ZTAoIlN1YmplY3QgIyIsIHAsICIgKFN0cmVzc29yPSIsIGFjdGl2aXR5X25hbWVzW1twXV0sICIpIiksIAogICAgICAgICAgICAgICAgeGF4aXM9bGlzdCh0aXRsZT0iRGlzdGFuY2UgW21dIiwgcmFuZ2U9YygwKSksIAogICAgICAgICAgICAgICAgeWF4aXM9eTEsIAogICAgICAgICAgICAgICAgeWF4aXMyPXkyLCAKICAgICAgICAgICAgICAgIG1hcmdpbiA9IGxpc3QobCA9IDUwLCByID0gNTAsIGIgPSA1MCwgdCA9IDUwLCBwYWQgPSA0KSwKICAgICAgICAgICAgICAgIHNoYXBlcyA9IGxpc3QoCiAgICAgICAgICAgICAgICAgICMgSG9saXN0aWMgcGVyaW9kCiAgICAgICAgICAgICAgICAgIGxpc3QodHlwZSA9ICJyZWN0IiwgZmlsbGNvbG9yID0gInJlZCIsIAogICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gInJlZCIpLCBvcGFjaXR5ID0gMC4zLAogICAgICAgICAgICAgICAgICAgICAgeDAgPSBpbmNpZGVudF9zdGFydGluZ190aW1lLCB4MSA9IGluY2lkZW50X2VuZGluZ190aW1lLCB4cmVmID0gIngiLAogICAgICAgICAgICAgICAgICAgICAgeTAgPSAwLCB5MSA9IDEwMCwgeXJlZiA9ICJ5IiksCiAgICAgICAgICAgICAgICAgICMgU3RyZXNzb3IgcGVyaW9kCiAgICAgICAgICAgICAgICAgIGxpc3QodHlwZSA9ICJyZWN0IiwgZmlsbGNvbG9yID0gInllbGxvdyIsIAogICAgICAgICAgICAgICAgICAgICAgIGxpbmUgPSBsaXN0KGNvbG9yID0gInllbGxvdyIpLCBvcGFjaXR5ID0gMC4xLAogICAgICAgICAgICAgICAgICAgICAgeDAgPSBzdHJlc3Nvcl9zdGFydF90aW1lc1tbcF1dLCB4MSA9IGluY2lkZW50X3N0YXJ0aW5nX3RpbWUsIHhyZWYgPSAieCIsCiAgICAgICAgICAgICAgICAgICAgICB5MCA9IDAsIHkxID0gMTAwLCB5cmVmID0gInkiKSwKICAgICAgICAgICAgICAgICAgbGlzdCh0eXBlID0gInJlY3QiLCBmaWxsY29sb3IgPSAieWVsbG93IiwgCiAgICAgICAgICAgICAgICAgICAgICAgbGluZSA9IGxpc3QoY29sb3IgPSAieWVsbG93IiksIG9wYWNpdHkgPSAwLjEsCiAgICAgICAgICAgICAgICAgICAgICB4MCA9IGluY2lkZW50X2VuZGluZ190aW1lLCB4MSA9IHN0cmVzc29yX2VuZF90aW1lc1tbcF1dLCB4cmVmID0gIngiLAogICAgICAgICAgICAgICAgICAgICAgeTAgPSAwLCB5MSA9IDEwMCwgeXJlZiA9ICJ5IikKICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICBsZWdlbmQgPSBsaXN0KHggPSAwLjEsIHkgPSAxLCBiZ2NvbG9yID0gInJnYmEoMCwwLDAsMCkiLCB0aXRsZT0iTWV0cmljIiksCiAgICAgICAgICAgICAgICBhdXRvc2l6ZSA9IEYKICAgICAgICAgICAgICApCiAgCiAgIyBvcmNhKHBsb3RfUFAsIGZuYW1lKQogIGlkeCA8LSBpZHggKyAxCiAgcGx0X0FsbEFjY1tbcF1dIDwtIHBsb3RfQWNjCn0KCmh0bWx0b29sczo6dGFnTGlzdChwbHRfQWxsQWNjKQpgYGAKCmBgYHtyLCB3YXJuaW5nPUZBTFNFfQojIGZvciAocCBpbiBwZXJzb25zKSB7CiMgICAjIFNhdmUgaW1hZ2UKIyAgIG9yY2EocGx0X0FsbEFjY1tbcF1dLCBmaWxlID0gcGFzdGUwKCIuLi9wbG90cy9kcml2ZS9Ecml2ZV80L1QwIiwgcCwgIi5wbmciKSwgc2NhbGUgPSAyKQojIH0KYGBgCgpgYGB7cn0KaWR4IDwtIDEKYmVoYXZpb3JhbENvbHVtbnMgPC0gYygiU3ViamVjdCIsIAogICAgICAgICAgICAgICAgICAgICAgICJCcmFrZV91IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIkJyYWtlX3N0ZCIsIAogICAgICAgICAgICAgICAgICAgICAgICJQUF9iZWZvcmUiLAogICAgICAgICAgICAgICAgICAgICAgICJQUF91IiwgIAogICAgICAgICAgICAgICAgICAgICAgICJQUF9zdGQiLAogICAgICAgICAgICAgICAgICAgICAgICJQUF9kZXYiKQpiZWhhdmlvcmFsTWF0cml4IDwtIG1hdHJpeChucm93PWxlbmd0aChwZXJzb25zKSwgbmNvbCA9IGxlbmd0aChiZWhhdmlvcmFsQ29sdW1ucykpCgojIENhcmVmdWwgYWJvdXQgU3ViamVjdCAwOQojIHNlbGVjdGVkX3BlcnNvbnMgPC0gcGVyc29uc1twZXJzb25zICE9ICIwOSJdCgpmb3IgKHAgaW4gcGVyc29ucykgewogIHBEYXRhIDwtIGFsbF9Ecml2ZTRbYWxsX0RyaXZlNCRTdWJqZWN0PT1hcy5pbnRlZ2VyKHApIHwgYWxsX0RyaXZlNCRTdWJqZWN0PT1wLF0KICAKICBpbmNpZGVudF9zdGFydGluZ190aW1lIDwtIGFjY19zdGFydF90aW1lc1tbcF1dICMgc3RhcnRpbmdfcG9pbnRzW2lkeF0KICBpbmNpZGVudF9lbmRpbmdfdGltZSA8LSBhY2NfZW5kX3RpbWVzW1twXV0KICAKICBmcm9tX3RpbWUgPC0gaWZlbHNlKGluY2lkZW50X3N0YXJ0aW5nX3RpbWUgLSBQUkVWX0RJU1RBTkNFID49IDAsIGluY2lkZW50X3N0YXJ0aW5nX3RpbWUgLSBQUkVWX0RJU1RBTkNFLCAwKQogIHRvX3RpbWUgPC0gY29tcGxldGVfdGltZXNbW3BdXQogICAgCiAgZGZCZWZvcmUgPC0gcERhdGFbcERhdGEkRGlzdGFuY2UgPCBpbmNpZGVudF9zdGFydGluZ190aW1lICYgcERhdGEkRGlzdGFuY2UgPj0gZnJvbV90aW1lLF0KICBkZkFmdGVyIDwtIHBEYXRhW3BEYXRhJERpc3RhbmNlID49IGluY2lkZW50X3N0YXJ0aW5nX3RpbWUgKyBERUxBWV9ESVNUQU5DRSAgJiBwRGF0YSREaXN0YW5jZSA8PSB0b190aW1lLF0KICAKICAjIGRpZmZTcGVlZCA8LSBtZWFuKGRmQWZ0ZXIkU3BlZWQpIC0gbWVhbihkZkJlZm9yZSRTcGVlZCkKICBicmFrZU1lYW4gPC0gbWVhbihkZkFmdGVyJEJyYWtpbmcpCiAgYnJha2VTdGQgPC0gbWVhbihkZkFmdGVyJEJyYWtpbmcpCiAgCiAgcHBNZWFuIDwtIG1lYW4oZGZBZnRlciRwcExvZ05vcm1hbGl6ZWQpCiAgcHBCZWZvcmUgPC0gbWVhbihkZkJlZm9yZSRwcExvZ05vcm1hbGl6ZWQpCiAgcHBTdGQgPC0gc2QoZGZBZnRlciRwcExvZ05vcm1hbGl6ZWQpCiAgCiAgbWlkX2F2ZyA8LSAocHBfYmFzZWxpbmVbW3BdXSArIG1lYW4oZGZCZWZvcmUkcHBMb2dOb3JtYWxpemVkKSkgLyAyCiAgICAKICBkaWZmUFAgPC0gbWVhbihkZkFmdGVyJHBwTG9nTm9ybWFsaXplZCkgLSBtZWFuKGRmQmVmb3JlJHBwTG9nTm9ybWFsaXplZCkKICAKICBiZWhhdmlvcmFsTWF0cml4W2lkeCwgXSA8LSBjKHAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQoYnJha2VNZWFuLCBkaWdpdHM9NSksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQoYnJha2VTdGQsIGRpZ2l0cz01KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHBwQmVmb3JlLCBkaWdpdHM9NSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3VuZChwcE1lYW4sIGRpZ2l0cyA9IDUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm91bmQocHBTdGQsIGRpZ2l0cz01KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdW5kKGRpZmZQUCwgZGlnaXRzPTUpKQogIGlkeCA8LSBpZHggKyAxCn0KCiMgYmVoYXZpb3JhbE1hdHJpeAoKYmVoYXZpb3JhbERmIDwtIGFzLmRhdGEuZnJhbWUoYmVoYXZpb3JhbE1hdHJpeCwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKbmFtZXMoYmVoYXZpb3JhbERmKSA8LSBiZWhhdmlvcmFsQ29sdW1ucwoKYmVoYXZpb3JhbERmCgpgYGAKCgpgYGB7cn0KY2x1c3RlcmluZ0RmIDwtIGJlaGF2aW9yYWxEZgpjbHVzdGVyaW5nRGYkU3ViamVjdCA8LSBOVUxMCiMgY2x1c3RlcmluZ0RmJFBQX2Rldl9ub3JtIDwtIGFzLm51bWVyaWMoY2x1c3RlcmluZ0RmJFBQX2RldikgLyBhcy5udW1lcmljKGNsdXN0ZXJpbmdEZiRQUF91KQojIGNsdXN0ZXJpbmdEZiRQUF9zdGRfbm9ybSA8LSBhcy5udW1lcmljKGNsdXN0ZXJpbmdEZiRQUF9zdGQpIC8gYXMubnVtZXJpYyhjbHVzdGVyaW5nRGYkUFBfdSkKY2x1c3RlcmluZ0RmJEJyYWtlX3UgPC0gTlVMTApjbHVzdGVyaW5nRGYkQnJha2Vfc3RkIDwtIE5VTEwKY2x1c3RlcmluZ0RmJFBQX2JlZm9yZSA8LSBOVUxMCmNsdXN0ZXJpbmdEZiRQUF91IDwtIE5VTEwKY2x1c3RlcmluZ0RmJFBQX3N0ZCA8LSBOVUxMCiMgY2x1c3RlcmluZ0RmJFBQX2RldiA8LSBOVUxMCgpyb3duYW1lcyhjbHVzdGVyaW5nRGYpIDwtIHBhc3RlMCgiIyIsIHBlcnNvbnMpCgpmb3IgKGNvbCBpbiBuYW1lcyhjbHVzdGVyaW5nRGYpKSB7CiAgY2x1c3RlcmluZ0RmWyxjb2xdIDwtIGFzLm51bWVyaWMoYXMuY2hhcmFjdGVyKGNsdXN0ZXJpbmdEZlssIGNvbF0pKQogICMgY2x1c3RlcmluZ0RmWyxjb2xdIDwtIHNjYWxlKGNsdXN0ZXJpbmdEZlssY29sXSkKfQpjbHVzdGVyaW5nRGYKYGBgCgpgYGB7cn0KZGZBY3Rpdml0eSA8LSBhbGxfRHJpdmU0W2FsbF9Ecml2ZTQkVGltZT09NjAsXSAlPiUgc2VsZWN0KGMoIlN1YmplY3QiLCAiQWN0aXZpdHkiKSkKZGZBY3Rpdml0eSRBY3Rpdml0eU5hbWUgPC0gc2FwcGx5KGRmQWN0aXZpdHkkQWN0aXZpdHksIGdldEFjdGl2aXR5TmFtZSkKZGZBY3Rpdml0eSRTdWJqZWN0IDwtIGFzLmZhY3RvcihkZkFjdGl2aXR5JFN1YmplY3QpCnJvd25hbWVzKGRmQWN0aXZpdHkpIDwtIE5VTEwKZGZBY3Rpdml0eSAlPiUgc2VsZWN0KGMoIlN1YmplY3QiLCAiQWN0aXZpdHlOYW1lIikpCmBgYAoKYGBge3J9CmxpYnJhcnkoZGVuZGV4dGVuZCkKCk5VTUJFUl9PRl9DTFVTVEVSUyA9IDMKCmNvbG9yX2RhcmtwaW5rID0gIiNlNzU0ODAiCkNMVVNURVJfQlJBTkNIX0NPTE9SUyA8LSBjKCJibHVlIiwgInJlZCIsIGNvbG9yX2RhcmtwaW5rKVsxOk5VTUJFUl9PRl9DTFVTVEVSU10KQ0xVU1RFUl9MQUJFTF9DT0xPUlMgPC0gYygiYmx1ZSIsICJyZWQiLCBjb2xvcl9kYXJrcGluaylbMTpOVU1CRVJfT0ZfQ0xVU1RFUlNdCgpiZWhhdmlvcmFsTWF0cml4Q2x1c3RlcmluZyA8LSBhcy5tYXRyaXgoY2x1c3RlcmluZ0RmKQpyb3duYW1lcyhiZWhhdmlvcmFsTWF0cml4Q2x1c3RlcmluZykgPC0gcGFzdGUwKGRmQWN0aXZpdHkkQWN0aXZpdHlOYW1lLCAiIC0gIyIsIHBlcnNvbnMpCmRpc3RNYXRyaXggPC0gZGlzdChiZWhhdmlvcmFsTWF0cml4Q2x1c3RlcmluZywgbWV0aG9kPSJtYW5oYXR0YW4iKQpocmVzdWx0cyA8LSBkaXN0TWF0cml4ICU+JSBoY2x1c3QKCmhjIDwtIGhyZXN1bHRzICU+JSAKICAgICAgYXMuZGVuZHJvZ3JhbSAlPiUKICAgICAgc2V0KCJub2Rlc19jZXgiLCBOVU1CRVJfT0ZfQ0xVU1RFUlMpICU+JQogICAgICBzZXQoImxhYmVsc19jb2wiLCB2YWx1ZSA9IENMVVNURVJfTEFCRUxfQ09MT1JTLCBrPU5VTUJFUl9PRl9DTFVTVEVSUykgJT4lCiAgICAgICMgc2V0KCJsZWF2ZXNfcGNoIiwgMTkpICU+JQogICAgICAjIHNldCgibGVhdmVzX2NvbCIsIHZhbHVlID0gYygiZ3JheSIpLCBrPU5VTUJFUl9PRl9DTFVTVEVSUykgJT4lICAgIAogICAgICBzZXQoImJyYW5jaGVzX2tfY29sb3IiLCB2YWx1ZT1DTFVTVEVSX0JSQU5DSF9DT0xPUlMsIGs9TlVNQkVSX09GX0NMVVNURVJTKQoKcGxvdChoYykKbGVnZW5kKCJ0b3ByaWdodCIsIAogICAgIHRpdGxlPSJEcml2ZT1GYWlsdXJlIFxuQ2hhbmdlIG9mIEFyb3VzYWwiLAogICAgIGxlZ2VuZCA9IGMoIkV4Y2VwdGlvbmFsIEluY3JlYXNlIiAsICJOb3RpY2FibGUgSW5jcmVhc2UiICwgIk5vLWNoYW5nZSBvciBEZWNyZWFzZSIpLCAKICAgICBjb2wgPSBjKCJyZWQiLCAicGluayIgLCAiYmx1ZSIpLAogICAgIHBjaCA9IGMoMjAsMjAsMjApLCBidHkgPSAibiIsICBwdC5jZXggPSAxLjUsIGNleCA9IDAuOCAsIAogICAgIHRleHQuY29sID0gImJsYWNrIiwgaG9yaXogPSBGQUxTRSwgaW5zZXQgPSBjKDAuMCwgMC4xKSkKYGBgCgpgYGB7cn0KTlVNQkVSX09GX0NMVVNURVJTID0gMgoKY29sb3JfZGFya3BpbmsgPSAiI2U3NTQ4MCIKQ0xVU1RFUl9CUkFOQ0hfQ09MT1JTIDwtIGMoImJsdWUiLCAicmVkIiwgY29sb3JfZGFya3BpbmspWzE6TlVNQkVSX09GX0NMVVNURVJTXQpDTFVTVEVSX0xBQkVMX0NPTE9SUyA8LSBjKCJibHVlIiwgInJlZCIsIGNvbG9yX2RhcmtwaW5rKVsxOk5VTUJFUl9PRl9DTFVTVEVSU10KCmJlaGF2aW9yYWxNYXRyaXhDbHVzdGVyaW5nIDwtIGFzLm1hdHJpeChjbHVzdGVyaW5nRGYpCnJvd25hbWVzKGJlaGF2aW9yYWxNYXRyaXhDbHVzdGVyaW5nKSA8LSBwYXN0ZTAoZGZBY3Rpdml0eSRBY3Rpdml0eU5hbWUsICIgLSAjIiwgcGVyc29ucykKZGlzdE1hdHJpeCA8LSBkaXN0KGJlaGF2aW9yYWxNYXRyaXhDbHVzdGVyaW5nLCBtZXRob2Q9Im1hbmhhdHRhbiIsIGRpYWcgPSBUKQpocmVzdWx0cyA8LSBkaXN0TWF0cml4ICU+JSBoY2x1c3QobWV0aG9kPSJhdmVyYWdlIikKCmhjIDwtIGhyZXN1bHRzICU+JSAKICAgICAgYXMuZGVuZHJvZ3JhbSAlPiUKICAgICAgc2V0KCJub2Rlc19jZXgiLCBOVU1CRVJfT0ZfQ0xVU1RFUlMpICU+JQogICAgICBzZXQoImxhYmVsc19jb2wiLCB2YWx1ZSA9IENMVVNURVJfTEFCRUxfQ09MT1JTLCBrPU5VTUJFUl9PRl9DTFVTVEVSUykgJT4lCiAgICAgICMgc2V0KCJsZWF2ZXNfcGNoIiwgMTkpICU+JQogICAgICAjIHNldCgibGVhdmVzX2NvbCIsIHZhbHVlID0gYygiZ3JheSIpLCBrPU5VTUJFUl9PRl9DTFVTVEVSUykgJT4lICAgIAogICAgICBzZXQoImJyYW5jaGVzX2tfY29sb3IiLCB2YWx1ZT1DTFVTVEVSX0JSQU5DSF9DT0xPUlMsIGs9TlVNQkVSX09GX0NMVVNURVJTKQoKcGxvdChoYykKbGVnZW5kKCJ0b3ByaWdodCIsIAogICAgIHRpdGxlPSJEcml2ZT1GYWlsdXJlIFxuQ2hhbmdlIG9mIEFyb3VzYWwiLAogICAgIGxlZ2VuZCA9IGMoIkFjY2VsZXJvcGhvYmlhIiAsICJOb3JtYWwiKSwgCiAgICAgY29sID0gYygicmVkIiwgImJsdWUiKSwKICAgICBwY2ggPSBjKDIwLDIwLDIwKSwgYnR5ID0gIm4iLCAgcHQuY2V4ID0gMS41LCBjZXggPSAwLjggLCAKICAgICB0ZXh0LmNvbCA9ICJibGFjayIsIGhvcml6ID0gRkFMU0UsIGluc2V0ID0gYygwLjAsIDAuMSkpCmBgYAoKYGBge3J9CiMgU3RvcmUgY2x1c3RlcmluZyBkYXRhCmRmeCA8LSBjbHVzdGVyaW5nRGYKZGZ4IDwtIGNiaW5kKHBlcnNvbnMsIGFzLm51bWVyaWMoYmVoYXZpb3JhbERmJFBQX2JlZm9yZSksIGFzLm51bWVyaWMoYmVoYXZpb3JhbERmJFBQX3UpLCBkZngsIGRmQWN0aXZpdHkkQWN0aXZpdHlOYW1lKQpuYW1lcyhkZngpIDwtIGMoIlN1YmplY3QiLCAiUFBfUHJpb3IiLCAiUFBfQWZ0ZXIiLCAiUFBfRGV2IiwgIkFjdGl2aXR5IikKCiMgTm9ybWFsaXplCmRmeCA8LSBkZnggJT4lIG11dGF0ZShQUF9EZXZfTm9ybWFsaXplZCA9IGlmZWxzZShQUF9QcmlvciA+IDAsIFBQX0FmdGVyLCBQUF9BZnRlciAtIFBQX1ByaW9yKSkKd3JpdGUuY3N2KGRmeCwgb3V0cHV0RmlsZSwgcm93Lm5hbWVzID0gRikKYGBgCgpgYGB7cn0KbGlicmFyeShjbHVzdGVyKQpmaXQgPC0ga21lYW5zKGNsdXN0ZXJpbmdEZiwgMikKY2x1c3Bsb3QoY2x1c3RlcmluZ0RmLCBmaXQkY2x1c3RlciwgY29sb3I9VFJVRSwgc2hhZGU9VFJVRSwKICAgbGFiZWxzPTIsIGxpbmVzPTApCmBgYAoKYGBge3J9CnNpbGhvdWV0dGVfc2NvcmUgPC0gZnVuY3Rpb24oayl7CiAga20gPC0ga21lYW5zKGNsdXN0ZXJpbmdEZiwgY2VudGVycyA9IGssIG5zdGFydD0yNSkKICBzcyA8LSBzaWxob3VldHRlKGttJGNsdXN0ZXIsIGRpc3QoY2x1c3RlcmluZ0RmKSkKICBtZWFuKHNzWywgM10pCn0KayA8LSAyOjEwCmF2Z19zaWwgPC0gc2FwcGx5KGssIHNpbGhvdWV0dGVfc2NvcmUpCnBsb3QoaywgdHlwZT0nYicsIGF2Z19zaWwsIHhsYWI9J051bWJlciBvZiBjbHVzdGVycycsIHlsYWI9J0F2ZXJhZ2UgU2lsaG91ZXR0ZSBTY29yZXMnLCBmcmFtZT1GQUxTRSkKYGBgCgojIyBMaW5lYXIgTW9kZWwKYGBge3J9CnNhbXBsZWREYXRhIDwtIGdldFNhbXBsZVNlZ21lbnRlZERhdGEoTkEsIGFsbF9Ecml2ZTQsIHdpbmRvdz0yKQpsaW5lYXJNb2RlbE9ubGluZSA8LSBsbWVyKHBwTmV4dCB+IAogICAgICAgICAgICAgICgxIHwgU3ViamVjdCkKICAgICAgICAgICAgICArIFNwZWVkX3UKICAgICAgICAgICAgICArIFNwZWVkX3N0ZAogICAgICAgICAgICAgICsgQWNjX3UKICAgICAgICAgICAgICArIEFjY19zdGQKICAgICAgICAgICAgICArIEJyYWtlX3UKICAgICAgICAgICAgICArIEJyYWtlX3N0ZAogICAgICAgICAgICAgICsgU3RlZXJpbmdfdQogICAgICAgICAgICAgICsgU3RlZXJpbmdfc3RkLCAKICAgICAgICAgICAgZGF0YT1zYW1wbGVkRGF0YSwgUkVNTCA9IFQpCgojIGxtZXIocHBMb2dOb3JtYWxpemVkIH4gKDEgfCBTdWJqZWN0KSArIFNwZWVkX3UgKyBTcGVlZF9zdGQgKyBBY2NfdSArIEFjY19zdGQgKyBCcmFrZV91ICsgQnJha2Vfc3RkICsgU3RlZXJpbmdfdSArIFN0ZWVyaW5nX3N0ZCArIEhSICsgQlIsIGRhdGEgPSBwRGF0YSwgUkVNTCA9IFQpCgojIGFub3ZhKG1vZGVsKQpzdW1tYXJ5KGxpbmVhck1vZGVsT25saW5lKQpwbG90KGxpbmVhck1vZGVsT25saW5lKQpgYGAK